package com.simple.relaxed.anno.impl;

import com.simple.relaxed.anno.Mark;
import com.simple.relaxed.manager.impl.InjectManager;
import com.simple.relaxed.utils.ReflectionsUtil;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;

public class MarkImpl {

    /**
     * 全局扫描被Mark注解标记的类，并且实例化注册到InjectManger中
     *
     * @throws NoSuchMethodException     找不到反方法时，抛出此异常
     * @throws InvocationTargetException 调用对象获取方法失败时，抛出此异常
     * @throws IllegalAccessException    传入的参数错误时，抛出此异常
     * @throws InstantiationException    当无法实例化时，抛出此异常
     */
    public static void initMark() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Set<Class<?>> classes = ReflectionsUtil.getClassByAnnotationClass(Mark.class);
        if (classes == null) {
            return;
        }
        for (Class<?> cls : classes) {
            Mark mark = cls.getDeclaredAnnotation(Mark.class);
            String bindName = mark.bindName();
            String methodName = mark.methodName();
            if (bindName.isEmpty()) {
                if (methodName.isEmpty()) {
                    Constructor<?> constructor = cls.getDeclaredConstructor();
                    constructor.setAccessible(true);
                    Object instance = constructor.newInstance();
                    InjectManager.getInstance().register(cls.getName(), instance);
                } else {
                    Method method = cls.getDeclaredMethod(methodName);
                    method.setAccessible(true);
                    Object invoke = method.invoke(null);
                    InjectManager.getInstance().register(cls.getName(), invoke);
                }
            } else {
                if (methodName.isEmpty()) {
                    Constructor<?> constructor = cls.getDeclaredConstructor();
                    constructor.setAccessible(true);
                    Object instance = constructor.newInstance();
                    InjectManager.getInstance().register(bindName, instance);
                } else {
                    Method method = cls.getDeclaredMethod(methodName);
                    method.setAccessible(true);
                    Object invoke = method.invoke(null);
                    InjectManager.getInstance().register(bindName, invoke);
                }
            }
        }
    }
}
